package com.yeyks.app.controller.weixin;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.yeyks.common.em.pay.PayAttach;
import com.yeyks.common.em.pay.PayTypeEnum;
import com.yeyks.common.utils.IdWorkerUtil;
import com.yeyks.common.utils.TryCatchUtil;
import com.yeyks.commonReference.append.mongodb.entity.PayCallbackRecordMongoEntity;
import com.yeyks.commonReference.append.mongodb.service.PayCallbackRecordMongoService;
import com.yeyks.commonReference.append.wxPay.config.WeChatYyksBaseConfigUtil;
import com.yeyks.commonReference.service.order.OrderPayRecordService;
import com.yeyks.commonReference.service.vip.MemberCardEnableRecordService;
import com.yeyks.commonReference.service.vip.MemberCardOnlineService;
import com.yeyks.commonReference.utils.PayUtil;
import com.yeyks.consumer.service.RechargeRecordService;
import com.yeyks.order.dal.domain.OrderPayRecord;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author fuchangshuai
 * @date 2019/5/6 0006
 */
@RestController
@Slf4j
@ApiIgnore
public class WxPayCallbackController {

    @Autowired
    private RechargeRecordService rechargeRecordService;
    @Autowired
    private OrderPayRecordService orderPayRecordService;
    @Autowired
    private PayCallbackRecordMongoService payCallbackRecordMongoService;
    @Autowired
    private MemberCardEnableRecordService memberCardEnableRecordService;
    @Autowired
    private WeChatYyksBaseConfigUtil wxConfigUtil;
    @Autowired
    private MemberCardOnlineService memberCardOnlineService;

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    /**
     * 统一微信支付回调（新版）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/wxPayCallbackNew")
    public String payCallbackNew(HttpServletRequest request) {
        try {
            String xmlStr = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            log.info("xmlStr = {}", xmlStr);
            WxPayOrderNotifyResult resultCode = wxConfigUtil.getWxPayService(PayTypeEnum.GZH.desc()).parseOrderNotifyResult(xmlStr);
            TryCatchUtil.tryCatch(() -> {
                payCallbackRecordMongoService.save(new PayCallbackRecordMongoEntity()
                        .setId(IdWorkerUtil.nextStrId())
                        .setCreateDate(new Date())
                        .setType(PayTypeEnum.WXPAY.desc())
                        .setRequestMessage(xmlStr)
                        .setText(JSONUtil.toJsonStr(resultCode)));
            });
            if (resultCode == null) {
                return WxPayNotifyResponse.fail("返回结果为空");
            }
            // 另起线程处理业务
            log.info("另起线程处理业务");
            executorService.execute(() -> disposeWork(resultCode));
            return WxPayNotifyResponse.success("处理成功!");
        } catch (Exception e) {
            log.error("微信支付回调结果异常,异常原因{}", e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

//    @PostConstruct
    public void doTest(){
        try {
            String xmlStr = "<xml><appid><![CDATA[wxdee60889e81703e8]]></appid>\n" +
                    "<attach><![CDATA[{\"orderType\":\"orderPay\",\"payType\":\"wxpay\"}]]></attach>\n" +
                    "<bank_type><![CDATA[LQT]]></bank_type>\n" +
                    "<cash_fee><![CDATA[200]]></cash_fee>\n" +
                    "<fee_type><![CDATA[CNY]]></fee_type>\n" +
                    "<is_subscribe><![CDATA[N]]></is_subscribe>\n" +
                    "<mch_id><![CDATA[1528638571]]></mch_id>\n" +
                    "<nonce_str><![CDATA[1571194173727]]></nonce_str>\n" +
                    "<openid><![CDATA[oga1Y6B6S_jTgGE-KVxenskzV-vc]]></openid>\n" +
                    "<out_trade_no><![CDATA[1184300244641251328]]></out_trade_no>\n" +
                    "<result_code><![CDATA[SUCCESS]]></result_code>\n" +
                    "<return_code><![CDATA[SUCCESS]]></return_code>\n" +
                    "<sign><![CDATA[F1A44042718E2431D75BC84012A7B0AD]]></sign>\n" +
                    "<time_end><![CDATA[20191016104939]]></time_end>\n" +
                    "<total_fee>200</total_fee>\n" +
                    "<trade_type><![CDATA[APP]]></trade_type>\n" +
                    "<transaction_id><![CDATA[4200000416201910166488366690]]></transaction_id>\n" +
                    "</xml>";
            WxPayOrderNotifyResult resultCode = wxConfigUtil.getWxPayService(PayTypeEnum.GZH.desc()).parseOrderNotifyResult(xmlStr);
            disposeWork(resultCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void disposeWork(WxPayOrderNotifyResult resultCode) {
        log.info("resultCode = {}", resultCode);
        String attach = resultCode.getAttach();
        Map<String, String> attachMap = PayUtil.getAttach(attach);
        String orderType = attachMap.get("orderType");
        String payType = attachMap.get("payType");
        boolean flag = false;
        // 支付成功
        if (resultCode.getResultCode().equals("SUCCESS")) {
            log.info("支付成功");
            flag = true;
        } else {
            log.info("支付失败");
        }
        //订单支付
        if (PayAttach.ORDER_PAY.desc().equals(orderType)) {
            String outTradeNo = resultCode.getOutTradeNo();
            //处理小程序订单,小程序订单以xcx结尾
            String desc = PayTypeEnum.XCX.desc();
            int xcxFlag = outTradeNo.indexOf(desc);
            if (xcxFlag > -1) {
                outTradeNo = outTradeNo.substring(0, xcxFlag);
            }
            //订单支付回调处理
            updateOrderPayRecord(outTradeNo, resultCode, payType, flag);
            orderPayRecordService.payCallback(outTradeNo, PayTypeEnum.getEnumFromDesc(payType), flag);
        }
        //会员卡支付
        else if (PayAttach.CARD_PAY.desc().equals(orderType)) {
            rechargeRecordService.payCardCallback(resultCode.getOutTradeNo(), flag);
        }
        //黑鱼礼包支付
        else if (PayAttach.BAG_GIFT_PAY.desc().equals(orderType)) {
            rechargeRecordService.paySmallBlackFishSpreeCallback(resultCode.getOutTradeNo(), flag);
        }
        // v3.4.a
        //会员卡enable支付(线下)
        else if (PayAttach.MEMBER_CARD_ENABLE_ORDER.desc().equals(orderType)) {
            String outTradeNo = resultCode.getOutTradeNo();
//            if (newFlag) {
            //处理小程序订单,小程序订单以xcx结尾
            String desc = PayTypeEnum.XCX.desc();
            int xcxFlag = outTradeNo.indexOf(desc);
            if (xcxFlag > -1) {
                outTradeNo = outTradeNo.substring(0, xcxFlag);
            }
            memberCardEnableRecordService.payCallback(outTradeNo, PayTypeEnum.getEnumFromDesc(payType), resultCode, flag);
        }
        //会员卡enable支付(线上)v3.8.3
        else if (PayAttach.MEMBER_CARD_ENABLE_ORDER_ONLINE.desc().equals(orderType)) {
            String outTradeNo = resultCode.getOutTradeNo();
//            if (newFlag) {
            //处理小程序订单,小程序订单以xcx结尾
            String desc = PayTypeEnum.XCX.desc();
            int xcxFlag = outTradeNo.indexOf(desc);
            if (xcxFlag > -1) {
                outTradeNo = outTradeNo.substring(0, xcxFlag);
            }
            memberCardOnlineService.payCallback(outTradeNo, PayTypeEnum.getEnumFromDesc(payType), resultCode, flag);
        }

    }

    private void updateOrderPayRecord(String orderNo, WxPayOrderNotifyResult notifyResult, String payType, Boolean paySuccess) {
        try {
            OrderPayRecord record = orderPayRecordService.getOne(new QueryWrapper<OrderPayRecord>()
                    .eq(OrderPayRecord.ORDER_NO, orderNo).eq(OrderPayRecord.PAY_TYPE, payType));
            if (record == null) {
                return;
            }
            record.setFinishTime(notifyResult.getTimeEnd());
            record.setPayReturnNo(notifyResult.getTransactionId());
            record.setPayResult(notifyResult.getResultCode());
            if (paySuccess) {
                record.setStatus("付款成功");
            } else {
                record.setStatus("付款超时");
            }
            orderPayRecordService.update(record);
        } catch (Exception e) {
            log.error("微信支付回调修改支付记录失败{}", e.getLocalizedMessage());
            e.printStackTrace();
        }
    }

}
